from airtest.core.api import *
from support.logging.log import *
from support.dbms.helper import *
from support.const.state import *
from support.device.os.device import *
from support.device.app.ui.analysis import *
from support.device.app.ui.confidence import *

class AppManager:
    def __init__(self, sn, appname, activity, datapath, depth = 5):
        Log._init_system(datapath)
        if('/' in appname):
            emt = appname.split('/')
            self.pkg = emt[0]
            self.activity = emt[1]
        else:
            self.pkg = appname
            self.activity = activity
        self.maxdepth = depth
        self.helper = SQLiteHelper(datapath, self.pkg)
        self.analyst = Analyst(connect_device('Android:///{}'.format(sn)), datapath, self.helper)
        self.log = Log(datapath, self.__class__.__name__)
        
    def start(self):
        if(self.activity is None):
            shell("am start '{}'".format(self.pkg))
        else:
            shell("am start -n '{}/{}'".format(self.pkg, self.activity))
        sleep(Global.WAIT_UI_TIMEOUT)
        
    def stop(self):
        shell("am force-stop {}".format(self.pkg))
        
    def clear(self):
        shell("pm clear {}".format(self.pkg))
        
    def getCurrentActivityName(self):
        ret = shell("dumpsys activity | grep \"Run #\"")
        lines = ret.split('\n')
        emt = lines[0].strip().split(' ')
        return emt[4].split('/')
        
    def hasAnyActivity(self):
        ret = shell("dumpsys activity | grep \"Run #\" | grep \"{}\"".format(self.pkg))
        return len(ret.split('\n'))
        
    def smartJumpBack(self):
        jumped = False
        screen = G.DEVICE.snapshot(None)
        if(UIConfidence.detectColor(screen, [[0,0,0],[0,0,0]]) > 0.95):
            self.log.info('检测到当前可能处于屏幕保护模式: 将跳过该界面')
            keyevent('BACK')
            jumped = True
        while(self.hasAnyActivity() > 0):
            pkg, activity = self.getCurrentActivityName()
            self.log.info('当前Activity:{} {}'.format(pkg, activity))
            if(pkg != self.pkg):
                self.log.info('当前界面并非 {} 所有，将强制跳转'.format(self.pkg))
                jumped = True
                keyevent('BACK')
                sleep(Global.WAIT_UI_TIMEOUT)
            else:
                break
        return jumped
        
    def automate(self, item, attrs, callback_method):
        if(callback_method):
            callback_method(item, attrs)
        else:
            if(attrs['touchable']):
                item.click()
            if(attrs['editable']):
                if(attrs['text'] != 'I am Robot'):
                    Device.text('I am Robot')
                keyevent('BACK')
        sleep(Global.WAIT_UI_TIMEOUT)
        return self.getCurrentActivityName()
        
    def calcdepth(self, activity, depth):
        if(self.smartJumpBack()):
            depth = self.maxdepth
        else:
            pkg, act = self.getCurrentActivityName()
            if(act == activity):
                depth -= 1
        return max(0,depth)
    def uiCrawOnlyFromDB(self, activity):
        Global.DEBUG_SHOW_MATCH_DETAIL = True
        Global.BLOB_SHOW_TIMEOUT = 0
        self.analyst.onlyMatchBlob(activity)
        self.helper.close()
        Global.DEBUG_SHOW_MATCH_DETAIL = False
        Global.BLOB_SHOW_TIMEOUT = 1000
        
    def uiCrawOnlyCurrent(self, activity):
        Global.DEBUG_SHOW_MATCH_DETAIL = False
        Global.BLOB_SHOW_TIMEOUT = 0
        self.helper.setMode(SQLiteHelper.MODE_DEBUG)
        while(True):
            ret = self.analyst.parseLayout(activity)
            if(ret is None or ret["code"] == ActivityState.COMPLETED):
                break
            if('depth' in ret):
                depth = max(0, ret['depth'] - 1)
            else:
                info = self.helper.getActivityState(activity)
                if(info is None):
                    depth = self.maxdepth
                else:
                    depth = max(0, info[2])
            compid = ret['id']
            if(compid == 0):
                self.helper.autoUpdateActivityInfo(activity, ret['blob'], depth, activity, 0, ActivityState.RUNNING)
            else:
                self.helper.updateComponentdepthById(activity, compid, depth)
        # self.helper.deleteDebugTable()
        self.helper.setMode(SQLiteHelper.MODE_NORMAL)
        self.helper.close()
        Global.DEBUG_SHOW_MATCH_DETAIL = False
        Global.BLOB_SHOW_TIMEOUT = 1000
        
    def uiCrawl(self, callback_method=None):
        while(True):
            jump_pkg = None
            jump_activity = None
            pkg, activity = self.getCurrentActivityName()
            if(activity is None):
                self.log.info('已无需遍历Activity，即将退出')
                break
            ret = self.analyst.parseLayout(activity)
            if('depth' in ret):
                depth = max(0, ret['depth'] - 1)
            else:
                info = self.helper.getActivityState(activity)
                if(info is None):
                    depth = self.maxdepth
                else:
                    depth = max(0, info[2])
            if(ret['code'] == ActivityState.COMPLETED):
                self.log.info('{} 已无需遍历的控件'.format(activity))
                self.helper.updateActivityState(activity, ActivityState.COMPLETED, depth)
                keyevent('BACK')
            else:
                compid = ret['id']
                jump_pkg, jump_activity = self.automate(ret['item'], ret['attrs'],callback_method)
                state = ActivityState.RUNNING
                if(self.smartJumpBack()):
                    jump_activity = "<jump_out>"
                    self.log.info('界面跳出 {}'.format(jump_pkg))
                    state = ActivityState.COMPLETED
                if(compid == 0):
                    self.helper.autoUpdateActivityInfo(activity, ret['blob'], depth, jump_activity, 0, state)
                else:
                    self.helper.updateComponentdepthById(activity, compid, depth)
        self.helper.close()
        
    @staticmethod
    def showBlob(dbpath, app, activity):
        helper = SQLiteHelper(dbpath, app)
        helper.getAllBlobFromActivity(activity,UIConfidence._show)
        helper.close()